(function(global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery', require('../util'))) :
    typeof define === 'function' && define.amd ? define(['jquery', '../util'], factory) :
    global.defineGd2d = factory($, gdutil);
}(this, function($, util) {
  'use strict';

  $.fn.draw = function(configs) {
    configs = configs || { fn: function() {} };
    var ctx = this[0].getContext('2d');
    configs.fn.call(this, ctx);
    return this;
  };

  $.fn.clearCanvas = function(p) {
    p = $.extend({
      x: 0,
      y: 0,
      width: this[0].width,
      height: this[0].height
    }, p);
    var ctx = this[0].getContext('2d');
    ctx.clearRect(p.x, p.y, p.width, p.height);
    return this;
  };

  var defineGd2d = function(configs) {
    configs = configs || {};
    if (!configs.name) {
      console.log('no function name!');
      return;
    } else if (!configs.name || $.fn[configs.name]) {
      console.log(configs.name + ' has been exist!');
      return;
    }

    var defaultOption = configs.props || {};

    $.fn[configs.name] = function(options) {
      //mix的时候都要注意，需要建立新对象
      options = $.extend({
        dWidth: this[0].width,
        dHeight: this[0].height
      }, defaultOption, options);

      this.each(function() {
        var ctx = this.getContext('2d');
        configs.fn.call(this, ctx, options);
      })
      return this;
    }
  };

  defineGd2d({
    name: 'drawText',
    props: {
      x: 0,
      y: 0,
      textAlign: 'start',
      textBaseline: 'alphabetic',
      direction: 'inherit',
      // font: '10px sans-serif',
      text: "",
      fillStyle: '',
      strokeStyle: '',
      lineWidth: 0
    },
    fn: function(ctx, p) {
      ctx.save();
      ctx.textAlign = p.textAlign;
      ctx.textBaseline = p.textBaseline;
      ctx.strokeStyle = p.strokeStyle;
      ctx.direction = p.direction;
      ctx.fillStyle = p.fillStyle;
      ctx.lineWidth = p.lineWidth;
      ctx.strokeStyle = p.strokeStyle;
      ctx.font = util.combineFont(p);
      if (p.fillStyle) {
        ctx.fillText(p.text, p.x, p.y);
      }
      if (p.strokeStyle && p.lineWidth) {
        ctx.strokeText(p.text, p.x, p.y)
      }
      ctx.restore();
    }
  });

  defineGd2d({
    name: 'drawImage',
    props: {
      sx: 0,
      sy: 0,
      dx: 0,
      dy: 0
    },
    fn: function(ctx, p, referenceCounting) {
      (referenceCounting && referenceCounting.acquire());
      var image = new Image();
      image.src = p.src;
      image.onload = function() {
        console.log(image.width, image.height)
        if (p.sWidth && p.sHeight) {
          ctx.drawImage(image, p.sx, p.sy, p.sWidth, p.sHeight, p.dx, p.dy, p.dWidth, p.dHeight);
        } else if (!p.zoomType || p.zoomType !== 'covered') {
          /**
           * 缩放到覆盖 cover
           * A为宽高比，A(a) < A(target)，宽度铺满，反之高度铺满
           */
          var crop; //等比裁剪
          if (image.width / image.height < p.dWidth / p.dHeight) {
            crop = {
              width: image.width,
              height: image.width * p.dHeight / p.dWidth
            }
          } else {
            crop = {
              width: image.height * p.dWidth / p.dHeight,
              height: image.height
            }
          }
          try {
            ctx.drawImage(image, p.sx, p.sy, crop.width || p.dWidth, crop.height || p.dHeight, p.dx, p.dy, p.dWidth, p.dHeight);
          } catch (e) {
            console.log(e)
          }
        } else {
          /**
           * 还需要一种缩放到被覆盖，并居中 (covered)
           */
          var target; //目标尺寸
          if (image.width / image.height > p.dWidth / p.dHeight) {
            target = {
              width: p.dWidth,
              height: p.dWidth * image.height / image.width
            }
            p.dy += (p.dHeight - target.height) / 2;
          } else {
            target = {
              width: p.dHeight * image.width / image.height,
              height: p.dHeight
            }
            p.dx += (p.dWidth - target.width) / 2;
          }
          try {
            ctx.drawImage(image, p.sx, p.sy, image.width || target.width, image.height || target.height, p.dx, p.dy, target.width, target.height);
          } catch (e) {
            console.log(e)
          }
        }
        (referenceCounting && referenceCounting.release());
      }
    }
  })

  $.extend({ defineGd2d: defineGd2d });
  return defineGd2d;
}))
